package org.inspursc.s0517.health.evaluation.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.*;
import org.inspursc.s0517.health.evaluation.converter.InsSurveyAnswerConverter;
import org.inspursc.s0517.health.evaluation.dto.*;
import org.inspursc.s0517.health.evaluation.entity.InsSurveyAnswer;
import org.inspursc.s0517.health.evaluation.entity.Organization;
import org.inspursc.s0517.health.evaluation.service.InsSurveyAppraiseService;
import org.inspursc.s0517.health.evaluation.utils.DataTypeUtil;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class InsFirstAssessmentServiceImpl implements InsSurveyAppraiseService {
    private Map<String, Integer> serviceLevelCount = new HashMap<>();

    /**
     * 根据调查记录评估调查报告
     * @param insSurveyAnswerDTO 问卷调查记录
     * @param organization 被评估对象
     * @param categoryDTOs 题目分类列表
     * @return InsSurveyAnswer 评估报告
     * @throws Exception
     */
    @Override
    public InsSurveyAnswer appraise(InsSurveyAnswerDTO insSurveyAnswerDTO, Organization organization, List<QuestionCategoryDTO> categoryDTOs) throws Exception {
        //get category and questions, assemble category id and question for assessment function
        Multimap<String, InsAnRadioDTO> anRadioDTOMultimap = ArrayListMultimap.create();
        insSurveyAnswerDTO.getQuestions().forEach(question ->{
            String categoryStr = question.getPrimaryCategoryId() + "-" + question.getSecondCategoryId();
            anRadioDTOMultimap.put(categoryStr,question);
        });

        //获取分类ID名字
        Map<Integer, String> cateNameMap = Maps.newHashMap();
        for (QuestionCategoryDTO categoryDTO : categoryDTOs) {
            cateNameMap.put(categoryDTO.getId(), categoryDTO.getName());
        }

        serviceLevelCount.put("A", 0);
        serviceLevelCount.put("B", 0);
        serviceLevelCount.put("C", 0);
        serviceLevelCount.put("Z", 0);
        //for get first category id and assemble its second category analyse detail
        Multimap<Integer, JSONObject> fristIdMultiMap = ArrayListMultimap.create();
        //get second category detail analyse report
        for (String secondCategoryKey : anRadioDTOMultimap.keySet()) {
            //get second category answer list
            List<InsAnRadioDTO> anRadios = ((ArrayListMultimap<String, InsAnRadioDTO>) anRadioDTOMultimap).get(secondCategoryKey);

            //get second category detail analyse report
            JSONObject secondCategoryKpi = this.getSecondCategoryKpi(secondCategoryKey, anRadios);
            //get second category name and set it to secondCategoryKpi
            String cataName = cateNameMap.get(Integer.parseInt(secondCategoryKey.substring(secondCategoryKey.lastIndexOf("-") + 1)));
            secondCategoryKpi.put("name", cataName);

            //get first category id for assemble
            Integer firstInt = Integer.parseInt(secondCategoryKey.substring(0, secondCategoryKey.lastIndexOf("-")));
            fristIdMultiMap.put(firstInt, secondCategoryKpi);
        }

        //first category list
        JSONArray categoryKpiArray = new JSONArray();
        Double total = 0.0;
        //assemble first category analyse report list
        for (Integer categoryId : fristIdMultiMap.keySet()) {
            //by first second category get second category list
            List<JSONObject> secondCategoryKpi = ((ArrayListMultimap<Integer, JSONObject>) fristIdMultiMap).get(categoryId);

            //assemble all info of first category
            JSONObject categoryKpi = this.getCategoryKpi(secondCategoryKpi, categoryId);
            categoryKpi.put("categoryId", categoryId);
            categoryKpi.put("name", cateNameMap.get(categoryId));

            if(categoryKpi.getDouble("score") != null){
                total += categoryKpi.getDouble("score");
            }
            categoryKpiArray.add(categoryKpi);
        }

        JSONObject assessmentKpi = new JSONObject();
//        assessmentKpi.put("anto_map", "{}");
        assessmentKpi.put("categoryKpi",categoryKpiArray);

        //asseble all analyse detail report
        String assessResult = getAssessResult(serviceLevelCount, total);
        StringBuffer description = new StringBuffer();
        description.append("甲等：" + serviceLevelCount.get("A").intValue() + "个；");
        description.append("乙等：" + serviceLevelCount.get("B").intValue() + "个；");
        description.append("丙等：" + serviceLevelCount.get("C").intValue() + "个；");
        description.append("不符合：" + serviceLevelCount.get("Z").intValue() + "个；");

        InsSurveyAnswer insSurveyAnswer = InsSurveyAnswerConverter.converter(insSurveyAnswerDTO);
        insSurveyAnswer.setAssessResult(assessResult);
        insSurveyAnswer.setTotalScore(DataTypeUtil.doubleFormatTwo(total));
        insSurveyAnswer.setKpi(JSONObject.toJSONString(assessmentKpi));
        insSurveyAnswer.setDescription(description.toString());
        insSurveyAnswer.setSuggestion("");
        return insSurveyAnswer;
    }

    /**
     * get first category score list
     */
    private JSONObject getCategoryKpi (List<JSONObject> secondCategoryKpi, Integer categoryId){
        JSONObject categoryKpi = new JSONObject();
        StringBuffer description = new StringBuffer();

        if(categoryId ==1 || categoryId == 2) {
            Map<String, Integer> thisServiceLevelCount = new HashMap<>();
            thisServiceLevelCount.put("A", 0);
            thisServiceLevelCount.put("B", 0);
            thisServiceLevelCount.put("C", 0);
            thisServiceLevelCount.put("Z", 0);
            for(JSONObject jsonObject : secondCategoryKpi) {
                if (jsonObject.get("secondCategoryServiceLevelCount") != null) {
                    Map<String, Integer> oneServiceLevelCount = (Map<String, Integer>) jsonObject.get("secondCategoryServiceLevelCount");
                    thisServiceLevelCount.put("A", thisServiceLevelCount.get("A").intValue() + oneServiceLevelCount.get("A").intValue());
                    thisServiceLevelCount.put("B", thisServiceLevelCount.get("B").intValue() + oneServiceLevelCount.get("B").intValue());
                    thisServiceLevelCount.put("C", thisServiceLevelCount.get("C").intValue() + oneServiceLevelCount.get("C").intValue());
                    thisServiceLevelCount.put("Z", thisServiceLevelCount.get("Z").intValue() + oneServiceLevelCount.get("Z").intValue());
                }
            }
            description.append("甲等：" + thisServiceLevelCount.get("A").intValue() + "个；");
            description.append("乙等：" + thisServiceLevelCount.get("B").intValue() + "个；");
            description.append("丙等：" + thisServiceLevelCount.get("C").intValue() + "个；");
            description.append("不符合：" + thisServiceLevelCount.get("Z").intValue() + "个；");
        }else {
            Double totalScore = secondCategoryKpi.stream()
                    .map(jsonObject -> jsonObject.getDouble("score"))
                    .mapToDouble(Double::doubleValue).sum();
            categoryKpi.put("score", DataTypeUtil.doubleFormatTwo(totalScore));
        }
        categoryKpi.put("secondCategoryKpi", secondCategoryKpi);
        categoryKpi.put("description", description.toString());
        return categoryKpi;
    }

    //return compute result to appraise function for assemble analyse report
    private JSONObject getSecondCategoryKpi(String cateId, List<InsAnRadioDTO> anRadioDTOS) {
        // assemble by data table named t_question_category  id & parent_id
        switch (cateId) {
            case "1-9":
            case "1-10":
            case "2-11":
            case "2-12":
            case "2-13":
            case "2-14":
            case "2-15":
                return this.getServiceLevelSecondCategoryKpi(anRadioDTOS);
            case "3-16":
            case "3-17":
            case "4-18":
            case "4-19":
            case "4-20":
            case "4-21":
            case "4-22":
            case "4-23":
            case "4-24":
            case "5-25":
            case "5-26":
            case "5-27":
            case "5-28":
            case "6-29":
            case "7-30":
            case "7-31":
            case "8-32":
                return this.getDefaultSecondCategoryKpi(anRadioDTOS);
            default:
                return this.getDefaultSecondCategoryKpi(anRadioDTOS);
        }
    }

    // 等级评估分类的二级分类评估算法
    private JSONObject getServiceLevelSecondCategoryKpi(List<InsAnRadioDTO> anRadioDTOList){
        JSONObject secondCategoryKpi = new JSONObject();
        Map<String, Integer> secondCategoryServiceLevelCount = new HashMap<>();
//        Integer score = 0;
        secondCategoryServiceLevelCount.put("A", 0);
        secondCategoryServiceLevelCount.put("B", 0);
        secondCategoryServiceLevelCount.put("C", 0);
        secondCategoryServiceLevelCount.put("Z", 0);

        StringBuffer description = new StringBuffer();
        for (InsAnRadioDTO radio : anRadioDTOList) {
            String oneOtherOptionsAnswer = radio.getOtherOptionsAnswer().size() > 0 ? radio.getOtherOptionsAnswer().toString() + "<br/>" : "";
            description.append(oneOtherOptionsAnswer);

            // 获取评估等级
            Integer optionScore = radio.getOptionScore();
            if(optionScore == 100){
                serviceLevelCount.put("A", serviceLevelCount.get("A").intValue() + 1);
                secondCategoryServiceLevelCount.put("A", secondCategoryServiceLevelCount.get("A").intValue() + 1);
            }else if(optionScore == 90){
                serviceLevelCount.put("B", serviceLevelCount.get("B").intValue() + 1);
                secondCategoryServiceLevelCount.put("B", secondCategoryServiceLevelCount.get("B").intValue() + 1);
            }else if(optionScore == 80){
                serviceLevelCount.put("C", serviceLevelCount.get("C").intValue() + 1);
                secondCategoryServiceLevelCount.put("C", secondCategoryServiceLevelCount.get("C").intValue() + 1);
            }else if(optionScore == 0){
                serviceLevelCount.put("Z", serviceLevelCount.get("Z").intValue() + 1);
                secondCategoryServiceLevelCount.put("Z", secondCategoryServiceLevelCount.get("Z").intValue() + 1);
            }
//            score =+ optionScore;
        }
        description.append("甲等：" + secondCategoryServiceLevelCount.get("A").intValue() + "个；");
        description.append("乙等：" + secondCategoryServiceLevelCount.get("B").intValue() + "个；");
        description.append("丙等：" + secondCategoryServiceLevelCount.get("C").intValue() + "个；");
        description.append("不符合：" + secondCategoryServiceLevelCount.get("Z").intValue() + "个；");
        secondCategoryKpi.put("secondCategoryServiceLevelCount", secondCategoryServiceLevelCount);
//        secondCategoryKpi.put("score", score);
        secondCategoryKpi.put("description",description.toString());
        return secondCategoryKpi;
    }

    // 默认二级分类评估算法
    private JSONObject getDefaultSecondCategoryKpi(List<InsAnRadioDTO> anRadios){
        JSONObject secondCategoryKpi = new JSONObject();
        StringBuffer description = new StringBuffer();
        Integer totalScore = anRadios.stream().mapToInt(InsAnRadioDTO::getOptionScore).sum();
        for(InsAnRadioDTO anRadio : anRadios){
            String oneOtherOptionsAnswer = anRadio.getOtherOptionsAnswer().size() > 0 ? anRadio.getOtherOptionsAnswer().toString() + "<br/>" : "";
            description.append(oneOtherOptionsAnswer);
        }
//        secondCategoryKpi.put("otherOptionsAnswer", otherOptionsAnswer);
        secondCategoryKpi.put("score", DataTypeUtil.doubleFormatTwo((double) totalScore / 100));
        secondCategoryKpi.put("description", description.toString());
        return secondCategoryKpi;
    }

    /**
     * 等级评测
     * @param serviceLevelCount
     * @param total
     * 三级甲等	92-103（含90）且“甲等”数≥30或95-103（含95）且“甲等”数≥28且“不符合” 数≤4
     * 三级乙等	（1）88-92（含88）且“甲等”数≥30或（2）92-95（含92）且“甲等”数≥28且“不符合” 数≤4或（3）95-100（含95）且“甲等”数≥20且≤27
     * 二级甲等	（1）85-88（含85）且“甲等”数≥30或（2）88-92（含88）且“甲等”数≥28且“不符合” 数≤4或（3）92-95（含92）且“甲等”数≥20且≤27
     * 二级乙等	（1）82-88（含82）且“甲等”数≥28或（2）85-92（含85）且“甲等”数≥20且≤27
     * 二级丙等	（1）79-82（含79）且“甲等”数≥28或（2）82-85（含82）且“甲等”数≥20且≤27
     * 一级	（1）70-79（含70）且“甲等”数≥20或（2）79-82（含79）且“甲等”数≥20且≤27
     * 无级	（1）＜70或（2）“甲等”数＜20
     * @return
     */
    private String getAssessResult(Map<String, Integer> serviceLevelCount, Double total){
        String assessResult = null;
//        if((serviceLevelCount.get("A").intValue() >=30 && total >= 92.0)
//                        || serviceLevelCount.get("Z").intValue() <= 4 && (serviceLevelCount.get("A").intValue() >= 28 && total>=95.0)){
//            assessResult = "三级甲等";
//        }else if((serviceLevelCount.get("A").intValue() >=30 && total >= 88.0 && total < 92.0)
//                || (serviceLevelCount.get("Z").intValue() <= 4 && serviceLevelCount.get("A").intValue() >=28 && total>=92.0 && total<95.0)
//                || (serviceLevelCount.get("A").intValue() >=20 && serviceLevelCount.get("A").intValue() <= 27 && total>=95.0)){
//            assessResult = "三级乙等";
//        }else if((serviceLevelCount.get("A").intValue() >=30 && total >= 85.0 && total < 88.0)
//                || (serviceLevelCount.get("Z").intValue() <= 4 && serviceLevelCount.get("A").intValue() >=28 && total>=88.0 && total<92.0)
//                ||(serviceLevelCount.get("A").intValue() >=20 && serviceLevelCount.get("A").intValue() <= 27 && total>=92.0 && total < 95.0)){
//            assessResult = "二级甲等";
//        }else if((serviceLevelCount.get("A").intValue() >=28 && total >= 82.0 && total < 88.0)
//                || (serviceLevelCount.get("A").intValue() >=20 && serviceLevelCount.get("A").intValue() <= 27 && total>=85.0 && total<92.0)){
//            assessResult = "二级乙等";
//        }else if((serviceLevelCount.get("A").intValue() >=28 && total >= 79.0 && total < 82.0)
//                || (serviceLevelCount.get("A").intValue() >=20 && serviceLevelCount.get("A").intValue() <= 27 && total>=82.0 && total<85.0)){
//            assessResult = "二级丙等";
//        }else if((serviceLevelCount.get("A").intValue() >=20 && total >= 70.0 && total < 79.0)
//                || (serviceLevelCount.get("A").intValue() >=20 && serviceLevelCount.get("A").intValue() <= 27 && total>=79.0 && total<82.0)){
//            assessResult = "一级";
//        }
        if(serviceLevelCount.get("A").intValue() < 20 || total < 70.0) {
            assessResult = "无级";
        }else if(serviceLevelCount.get("A").intValue() >=30 && total >= 85.0) {
            if(total >= 92) {
                assessResult = "三级甲等";
            }else if(total >= 88.0){
                assessResult = "三级乙等";
            }else if(total >= 85.0){
                assessResult = "二级甲等";
            }
        }else if(serviceLevelCount.get("A").intValue() >= 28) {
            if(total >= 88.0 && serviceLevelCount.get("Z").intValue() <= 4) {
                if (total >= 95.0) {
                    assessResult = "三级甲等";
                } else if (total >= 92.0) {
                    assessResult = "三级乙等";
                } else {
                    assessResult = "二级甲等";
                }
            }else {
                if (total >= 82.0 && total < 88.0) {
                    assessResult = "二级乙等";
                } else if (total >= 79.0) {
                    assessResult = "二级丙等";
                } else if (total >= 70.0) {
                    assessResult = "一级";
                }
            }
        }else if(serviceLevelCount.get("A").intValue() >= 20 && serviceLevelCount.get("A").intValue() <= 27){
            if(total>=95.0){
                assessResult = "三级乙等";
            }else if(total>=92.0){
                assessResult = "二级甲等";
            }else if(total>=85.0){
                assessResult = "二级乙等";
            }else if(total>=82.0){
                assessResult = "二级丙等";
            }else if(total>=70.0){
                assessResult = "一级";
            }
        }else{
            assessResult = "评估方案缺失";
        }
        return assessResult;
    }
}
